#ifndef ___fat32_subtransaccion15_cambiar_tamano_asignacion_archivo

#define ___fat32_subtransaccion15_cambiar_tamano_asignacion_archivo

#include "f32_mto.c"

#include "f32_opAL.c"
#include "f32_opAM.c"
#include "f32_opAT.c"
#include "f32_opBA.c"
#include "f32_opBB.c"
#include "f32_opBC.c"

struct fat32st15_datos {
  unsigned long clusterInicial;
  unsigned int numeroEntrada;
  unsigned long nuevoTamano;
  unsigned int conexion;
  unsigned long * cadena;
  unsigned long ultimoActual;
  fat32_lista_bloques_para_escribir * lbpe;
  unsigned long numeroBloque;
  char bloque[2048];
  unsigned short offsetBloque;
  unsigned long clusterInicialActual;
  unsigned long tamanoActual;
  unsigned long primeroNuevo;
};

unsigned char fat32st_cambiar_tamano_asignacion_archivo(unsigned char, unsigned int, unsigned long, unsigned int, unsigned long,
                                                                                                 void **, unsigned char, void *);

unsigned char fat32st_cambiar_tamano_asignacion_archivo (unsigned char estado, unsigned int transaccion, unsigned long clusterInicialDir,
                                                         unsigned int numeroEntrada, unsigned long nuevoTamano, void ** datos,
                                                         unsigned char estadoOp, unsigned int datosOp) {
  struct fat32st15_datos * datosST = *datos;
  switch (estado) {
    case 0.
      datosST = malloc(sizeof(struct fat32st15_datos));
      *datos = datosST;
      datosST -> clusterInicial = clusterInicialDir;
      datosST -> numeroEntrada = numeroEntrada;
      datosST -> nuevoTamano = nuevoTamano;
      datosST -> conexion = fat32_obtener_conexion_para_transaccion(transaccion);
      return 1;
    case 1:
      fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_clusteres, &(datosST -> clusterInicial), sizeof (datosST -> clusterInicial);
      return 2;
    case 2:
      datosST -> cadena = datosOp;
      fat32_quitar_operacion(transaccion);
      unsigned long cantidadClusteresDir;
      for (cantidadClusteresDir = 0; (datosST -> cadena)[cantidadClusteresDir]; cantidadClusteresDir ++);
      fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_sectores_desde_clusteres, &(datosST -> cadena),
                                                             sizeof(unsigned long) * (cantidadClusteresDir + 1));
      return 3;
    case 3:
      free(datosST -> cadena);
      datosST -> cadena = datosOp;
      fat32_quitar_operacion(transaccion);
      datosST -> numeroBloque = (datosST -> cadena)[(datosST -> numeroEntrada) / 16];
      datosST -> offsetBloque = 512 * ((datosST -> numeroBloque) & 3);
      datosST -> numeroBloque &= 3;
      datosST -> offsetBloque += 32 * ((datosST -> numeroEntrada) % 16);
      struct fat32opAM_solicitud_bloque ds;
      ds.sector = datosST -> numeroBloque;
      ds.conexion = datosST -> conexion;
      ds.buffer = datosST -> bloque;
      fat32_crear_operacion(transaccion, &fat32op_solicitar_bloque, &ds, sizeof ds);
      return 4;
    case 4:
      fat32_quitar_operacion(transaccion);
      free(datosST -> cadena);
      unsigned long cl1 = fb_convertir_de_little_endian((datosST -> bloque) + (datosST -> offsetBloque) + 26, 16);
      unsigned long cl2 = fb_convertir_de_little_endian((datosST -> bloque) + (datosST -> offsetBloque) + 20, 16);
      cl2 <<= 16;
      datosST -> clusterInicioActual = cl2 + cl1;
      datosST -> tamanoActual = fb_convertir_de_little_endian((datosST -> bloque) + (datosST -> offsetBloque) + 28, 32);
      if (!(datosST -> clusterInicioActual)) {
        datosST -> cadena = NULL;
        datosST -> ultimoActual = 0;
        return 6;
      }
      fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_clusteres, &(datosST -> clusterInicioActual), 
                                                                      sizeof (datosST -> clusterInicioActual));
      return 5;
    case 5:
      datosST -> cadena = datosOp;
      fat32_quitar_operacion(transaccion);
      unsigned long posicionC;
      for (posicionC = 0; (datosST -> cadena)[posicionC + 1]; posicionC ++);
      datosST -> ultimoActual = (datosST -> cadena)[posicionC];
      return 6;
    case 6;
      if (!(datosST -> nuevoTamano) && (datosST -> tamanoActual)) return 13;
      if ((datosST -> nuevoTamano) > (datosST -> tamanoActual)) return 7;
      if ((datosST -> nuevoTamano) < (datosST -> tamanoActual)) return 11;
      return 15;
    case 7:
      46;
      unsigned long clusteresActuales, clusteresNuevos;
      clusteresActuales = ((datosST -> tamanoActual) + 511) / 512;
      clusteresNuevos = ((datosST -> nuevoTamano) + 511) / 512;
      clusteresNuevos -= clusteresActuales;
      if (!clusteresNuevos) return 9;
      struct fat32opBA_datos_solicitud dnc;
      dnc.ultimoClusterActual = datosST -> ultimoActual;
      dnc.cantidad = clusteresNuevos;
      fat32_crear_operacion(transaccion, &fat32op_obtener_clusteres_adicionales, &dnc, sizeof dnc);
      return 8;
    case 8:
      if (estadoOp == 2) {
        fat32_quitar_operacion(transaccion);
        return 10;
      }
      datosST -> primeroNuevo = *((unsigned long *) datosOp);
      free(datosOp);
      fat32_quitar_operacion(transaccion);
      return 9;
    case 9:
      datosST -> lbpe = malloc(sizeof(fat32_lista_bloques_para_escritura));
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_LBPE_CREAR, &(datosST -> lbpe), 0, 0, 0, NULL);
      char numeroNuevo[4];
      if (!(datosST -> ultimoActual)) {
        fat32_convertir_a_little_endian(numeroNuevo, datosST -> primeroNuevo, 32);
        fat32_operar_sobre_lista_bloques_para_escritura(FAT32_ESCRIBIR, &(datosST -> lbpe), datosST -> numeroBloque,
                                                                       datosST -> offsetBloque + 26, 2, numeroNuevo);
        fat32_operar_sobre_lista_bloques_para_escritura(FAT32_ESCRIBIR, &(datosST -> lbpe), datosST -> numeroBloque,
                                                                   datosST -> offsetBloque + 20, 2, numeroNuevo + 2);
      }
      fat32_convertir_a_little_endian(numeroNuevo, datosST -> nuevoTamano, 32);
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_ESCRIBIR; &(datosST -> lbpe), datosST -> numeroBloque,
                                                                     datosST -> offsetBloque + 28, 4, numeroNuevo);
      return 16;
    case 10:
      datosST -> lbpe = NULL;
      return 16;
    case 11:
      46;
      unsigned long nuevoUltimoCluster;
      nuevoUltimoCluster = ((datosST -> nuevoTamano) - 1) / (512 * bootsector.sectoresPorCluster);
      nuevoUltimoCluster = (datosST -> cadena)[nuevoUltimoCluster];
      fat32_crear_transaccion(transaccion, &fat32op_desvincular_clusteres, &nuevoUltimoCluster, sizeof nuevoUltimoCluster);
      return 12;
    case 12:
      fat32_quitar_operacion(transaccion);
      datosST -> lbpe = malloc(sizeof(fat32_lista_bloques_para_escritura));
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_LBPE_CREAR, &(datosST -> lbpe), 0, 0, 0, NULL);
      char numero2[4];
      fat32_convertir_a_little_endian(numero2, datosST -> nuevoTamano, 32);
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_ESCRIBIR; &(datosST -> lbpe), datosST -> numeroBloque,
                                                                         datosST -> offsetBloque + 28, 4, numero2);
      return 16;
    case 13:
      fat32_crear_operacion(transaccion, &fat32op_eliminar_cadena_clusteres, datosST -> cadena, sizeof (unsigned long));
      return 14;
    case 14:
      fat32_quitar_operacion(transaccion);
      datosST -> lbpe = malloc(sizeof(fat32_lista_bloques_para_escritura));
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_LBPE_CREAR, &(datosST -> lbpe), 0, 0, 0, NULL);
      char numero0[4];
      char pos;
      for (pos = 0; pos < 4; pos ++) numero0[pos] = 0;
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_ESCRIBIR; &(datosST -> lbpe), datosST -> numeroBloque,
                                                                         datosST -> offsetBloque + 28, 4, numero2);
      return 16;
    case 15:
      datosST -> lbpe = malloc(sizeof(fat32_lista_bloques_para_escritura));
      fat32_operar_sobre_lista_bloques_para_escritura(FAT32_LBPE_CREAR, &(datosST -> lbpe), 0, 0, 0, NULL);
      return 16;
    case 16:
      if (datosST -> cadena) free(datosST -> cadena);
      *datos = datosST -> lbpe;
      free(datosST);
      return 0;
  }
}

#endif